package editorsvg.gui.generico;

import java.util.List;
import java.util.Vector;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;

/**
 * Restaura el estado de los nodos (expandidos/colapsados) del arbol de objetos.
 * @author Jorge Berjano
 */
public class RestauradorArbol implements TreeWillExpandListener {

    private JTree arbol;
    private List<TreePath> listaNodosExpandidos = new Vector<TreePath>();
    private TreePath[] nodosSeleccionados;
    private boolean restaurando = false;

    public RestauradorArbol(JTree arbol) {
        this.arbol = arbol;
        arbol.addTreeWillExpandListener(this);
    }
    
    public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
        if (!restaurando) {
            listaNodosExpandidos.remove(event.getPath());
//            System.out.println("Nodo colapsado: " + event.getPath());
        }
    }

    public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {

        if (!restaurando) {
            TreePath nodo = event.getPath();
            if (!listaNodosExpandidos.contains(nodo)) {
                listaNodosExpandidos.add(nodo);
//                System.out.println("nodo expandido: " + event.getPath());
            }
        }
    }
    
    /**
     * Guarda el estado de los nodos.
     */
    public synchronized void guardarEstado() {
        nodosSeleccionados = arbol.getSelectionPaths();        
    }

    /**
     * Restaura el estado de los nodos (expandido/colapsado) y la seleccion de nodos
     * que se guard�.
     */
    public synchronized void restaurarEstado() {
        
        Vector<TreePath> nuevaListaNodosExpandidos = new Vector<TreePath>();
        
        restaurando = true;

        for (int i = 0; i < listaNodosExpandidos.size(); i++) {
            TreePath nodo = listaNodosExpandidos.get(i);
            
            if (estaExpandido(nodo)) {
                arbol.expandPath(nodo);
                nuevaListaNodosExpandidos.add(nodo);
            }
        }
        
        listaNodosExpandidos = nuevaListaNodosExpandidos;
        
        arbol.setSelectionPaths(nodosSeleccionados);
        
        restaurando = false;

// Esto no funciona Error de concurrencia.        
//        for (TreePath nodo : listaNodosExpandidos) {
//            arbolObjetos.expandPath(nodo);
//        }
    }

    private boolean estaExpandido(TreePath nodo) {
        if (nodo.equals(arbol.getPathForRow(0)))
            return true;
        
        if (!listaNodosExpandidos.contains(nodo))
            return false;
        
        TreePath padre = nodo.getParentPath();
        if (padre == null) {
            return true;
        } else {
            return estaExpandido(padre);
        }            
    }

    public boolean isRestaurando() {
        return restaurando;
    }
}
